package com.tencent.ticsdk.core.recorder;

import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.util.Log;

/**
 * @ProjectName: ayoka7.
 * @ClassName: AudioRecordManager.
 * @Description: .
 * @Author: jincp.
 * @CreateDate: 2019/9/12 17:38.
 */
public class AudioRecordManager {

    public static final String TAG = "AudioRecordManager";

    //音频输入-麦克风
    private final static int AUDIO_INPUT = MediaRecorder.AudioSource.MIC;
    //采用频率
    //44100是目前的标准，但是某些设备仍然支持22050，16000，11025 48000
    //采样频率一般共分为22.05KHz、44.1KHz、48KHz三个等级
    public final static int AUDIO_SAMPLE_RATE = 48000;
    //声道 单声道
    private final static int AUDIO_CHANNEL = AudioFormat.CHANNEL_IN_MONO;
    //编码
    private final static int AUDIO_ENCODING = AudioFormat.ENCODING_PCM_16BIT;

    private static AudioRecordManager instance;

    private AudioRecord audioRecord;

    private int bufferSize;

    private boolean isRecording = false;

    private Thread recordThread;

    //录音监听
    private RecordStreamListener recordStreamListener;

    /**
     * 获取单例引用
     *
     * @return
     */
    public static AudioRecordManager getInstance() {
        if (instance == null) {
            synchronized (AudioRecordManager.class) {
                if (instance == null) {
                    instance = new AudioRecordManager();
                }
            }
        }
        return instance;
    }

    public AudioRecordManager() {
        bufferSize = AudioRecord.getMinBufferSize(AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING);
        Log.d(TAG, "bufferSize = " + bufferSize);
        audioRecord = new AudioRecord(AUDIO_INPUT, AUDIO_SAMPLE_RATE, AUDIO_CHANNEL, AUDIO_ENCODING, bufferSize);

    }

    /**
     * 启动录音
     */
    public void startRecord() {
        try {
            startThread();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 停止录音
     */
    public void stopRecord() {
        try {
            destroyThread();
            if (audioRecord != null) {
                if (audioRecord.getState() == AudioRecord.STATE_INITIALIZED) {
                    audioRecord.stop();
                }
                if (audioRecord != null) {
                    audioRecord.release();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 启动录音线程
     */
    private void startThread() {
        destroyThread();
        isRecording = true;
        if (recordThread == null) {
            recordThread = new Thread(recordRunnable);
            recordThread.start();
        }
    }


    /**
     * 销毁线程方法
     */
    private void destroyThread() {
        try {
            isRecording = false;
            if (null != recordThread && Thread.State.RUNNABLE == recordThread.getState()) {
                try {
                    Thread.sleep(500);
                    recordThread.interrupt();
                } catch (Exception e) {
                    recordThread = null;
                }
            }
            recordThread = null;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            recordThread = null;
        }
    }


    /**
     * 录音线程
     */
    private Runnable recordRunnable = new Runnable() {
        @Override
        public void run() {
            try {
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
                int bytesRecord;
                //int bufferSize = 320;

                if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
                    stopRecord();
                    return;
                }
                byte[] rawData = new byte[1920];
                audioRecord.startRecording();
                while (isRecording) {
                    if (null != audioRecord) {
                        bytesRecord = audioRecord.read(rawData, 0, 1920);
                        if (bytesRecord == AudioRecord.ERROR_INVALID_OPERATION || bytesRecord == AudioRecord.ERROR_BAD_VALUE) {
                            continue;
                        }
                        if (bytesRecord != 0 && bytesRecord != -1) {
                            //在此可以对录制音频的数据进行二次处理 比如变声，压缩，降噪，增益等操作

                            // 我们这里直接将pcm音频原数据写入文件
                            // 这里可以直接发送至服务器 对方采用AudioTrack进行播放原数据
                            // 直接把数据发送出去
                            process(rawData, 1920);
                        } else {
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };



    private  void process(byte[] rawData, int bufferSize) {
        try {
//          // 返回编码后的数据
//            speex.cancelNoisePreprocess(rawData, bufferSize);
            StringBuilder stringBuilder = new StringBuilder();
            for (byte b : rawData) {
                stringBuilder.append(b);
                stringBuilder.append(",");
            }
            Log.d(TAG, "rawData = " + stringBuilder.toString());
            if (recordStreamListener != null) {
                //用于拓展业务
                recordStreamListener.recordOfByte(rawData, 0, bufferSize);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private  void destroy() {
        destroyThread();
        if (instance != null) {
            instance = null;
        }
        if (audioRecord != null) {
            audioRecord = null;
        }
    }

    public void setRecordStreamListener(RecordStreamListener listener) {
        this.recordStreamListener = listener;
    }

    public static short[] toShortArray(byte[] src) {

        int count = src.length >> 1;
        short[] dest = new short[count];
        for (int i = 0; i < count; i++) {
            dest[i] = (short) (src[i * 2] << 8 | src[2 * i + 1] & 0xff);
        }
        return dest;
    }

    public static byte[] toByteArray(short[] src) {

        int count = src.length;
        byte[] dest = new byte[count << 1];
        for (int i = 0; i < count; i++) {
            dest[i * 2] = (byte) (src[i] >> 8);
            dest[i * 2 + 1] = (byte) (src[i] >> 0);
        }

        return dest;
    }
}
